﻿using RabbitMQ.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RMQProducter
{
    class Program
    {
        /// <summary>
        /// 连接配置
        /// </summary>
        private static readonly ConnectionFactory rabbitMqFactory = new ConnectionFactory()
        {
            HostName = "47.104.91.239",
            UserName = "yang",
            Password = "yang12345",
            Port = 5672
        };
        /// <summary>
        /// 路由名称
        /// </summary>
        const string ExchangeName = "justin.exchange";

        //队列名称
        const string QueueName = "justin.queue";

        /// <summary>
        /// 路由名称
        /// </summary>
        const string TopExchangeName = "topic.justin.exchange";

        //队列名称
        const string TopQueueName = "topic.justin.queue";


        static void Main(string[] args)
        {
            //DirectExchangeSendMsg();
            TopicExchangeSendMsg();
            Console.WriteLine("按任意值，退出程序");
            Console.ReadKey();
        }
        /// <summary>
        ///  单点精确路由模式
        /// </summary>
        public static void DirectExchangeSendMsg()
        {
            using (IConnection conn = rabbitMqFactory.CreateConnection())
            {
                using (IModel channel = conn.CreateModel())
                {
                    channel.ExchangeDeclare(ExchangeName, "direct", durable: true, autoDelete: false, arguments: null);
                    channel.QueueDeclare(QueueName, durable: true, autoDelete: false, exclusive: false, arguments: null);
                    channel.QueueBind(QueueName, ExchangeName, routingKey: QueueName);

                    var props = channel.CreateBasicProperties();
                    props.Persistent = true;
                    string vadata = "";
                    int count = 0;
                    while (true)
                    {
                        vadata = $"direct {count++}";
                        var msgBody = Encoding.UTF8.GetBytes(vadata);
                        channel.BasicPublish(exchange: ExchangeName, routingKey: QueueName, basicProperties: props, body: msgBody);
                        Console.WriteLine($"***发送时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}，发送内容{vadata}");
                        //vadata = Console.ReadLine();
                    }
                }
            }
        }
        /// <summary>
        /// 一个Exchange可以绑定多个队列
        /// 一个队列里可以有多个routingkey
        /// 一个消费者只能绑定一个队列，不能绑定多个队列
        /// 一个队列可以有多个消费者
        /// https://www.cnblogs.com/purpleraintear/p/6033136.html
        /// https://www.cnblogs.com/xibei666/p/5931267.html
        /// </summary>
        public static void TopicExchangeSendMsg()
        {
            using (IConnection conn = rabbitMqFactory.CreateConnection())
            {
                using (IModel channel = conn.CreateModel())
                {
                    channel.ExchangeDeclare(TopExchangeName, "topic", durable: true, autoDelete: false, arguments: null);
                    channel.QueueDeclare(TopQueueName, durable: true, autoDelete: false, exclusive: false, arguments: null);
                    channel.QueueDeclare("ASDF", durable: true, autoDelete: false, exclusive: false, arguments: null);
                    channel.QueueBind(TopQueueName, TopExchangeName, routingKey: TopQueueName);
                    channel.QueueBind("ASDF", TopExchangeName, routingKey: "ASDF");
                    var props = channel.CreateBasicProperties();
                    props.Persistent = true;
                    props.DeliveryMode = 2;    //1表示不持久，2表示持久化
                    string vadata = "";
                    var count = 0;
                    while (count <= 10)
                    {
                        //存消息与routingkey有关，根据routingkey确定存储到哪个队列上，取消息与routingkey无关，只与队列有关
                        string routingkey = count % 2 == 0 ? "1122" : "11";
                        //绑定只有在没有保存过数据时才起效，如果第一次保存过，第二次去掉绑定关系，也可以执行成功，因为绑定关系已经存在
                        //如果一个routingkey已经绑定过两个队列，哪怕本次操作只有一个队列，只要之前的绑定关系还存在，本次会向两个队列中都保存数据
                        //channel.QueueBind(TopQueueName, TopExchangeName, routingKey: TopQueueName);
                        vadata = $"topic {count++}";
                        var msgBody = Encoding.UTF8.GetBytes(vadata);
                        channel.BasicPublish(exchange: TopExchangeName, routingKey: TopQueueName, basicProperties: props, body: msgBody);
                        channel.BasicPublish(exchange: TopExchangeName, routingKey: "ASDF", basicProperties: props, body: msgBody);
                        Console.WriteLine($"***发送时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}，发送内容{vadata}");
                    }
                }
            }
        }
    }
}
